home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
presto
/
presto10.lha
/
src
/
shbrk.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-12-11
|
7KB
|
312 lines
/* $Copyright: $
* Copyright (c) 1984, 1985, 1986 Sequent Computer Systems, Inc.
* All rights reserved
*
* This software is furnished under a license and may be used
* only in accordance with the terms of that license and with the
* inclusion of the above copyright notice. This software may not
* be provided or otherwise made available to, or used by, any
* other person. No title to or ownership of the software is
* hereby transferred.
*/
#ifndef lint
static char rcsid[] = "$Header: shbrk.c 1.3 88/03/31 $";
#endif
/*
* shbrk.c
* Parallel run-time basic shared memory allocator.
*
* Heavily based on Sequent parallel programming library shared memory
* manager. Greatly simplified.
*/
/* $Log: shbrk.c,v $
* Revision 1.3 88/03/31 15:39:43 rbk
* Drop all refs to "do_shared_stack" (not necessary, and value was 0).
* Also drop all refs to _single_stack -- not needed, since signal handling
* much simpler than microtasking code (child processes don't trap signals).
* _init_shstk() is now a NOP since not using the microtasking library's
* "shared stack"; drop other junk dealing with this shared stack
* (misc #define's, variables, grow_stack()).
* Other simplifications for simpler environment.
*
* Revision 1.2 88/03/24 09:52:32 rbk
* Import MMAP macro, drop #include of parc.h. Also #unifdef -DCONCAT.
*
* Revision 1.1 88/03/22 15:23:28 rbk
* Initial revision
*
*/
#ifdef sequent
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/file.h>
/*#include <stddef.h>*/
#include <sys/mman.h>
#include <sys/signal.h>
#include <parallel/parallel.h>
#define MMAP(fd,va,sz,pos) \
mmap(va, sz, PROT_READ|PROT_WRITE, MAP_SHARED, fd, pos)
/*
* Module local variables.
*/
private int priv_stack_limit; /* size limit for priv stack */
private static char *myshbrk; /* process local max sbrk */
shared static char *curshbrk; /* global for all processes */
shared static slock_t shbrk_lock = L_UNLOCKED;
/*
* _init_shbrk()
* Initialize basic shared-memory allocator.
*
* Called from _ppinit().
*
* Since the memory manager comes into play on a SEGV signal, we have to be
* careful that we don't get preempted at any point from within this handler,
* since the "state" represented by the fp and sp are transient. This routine
* must be allowed to finish without interruption.
*
* We also block the SIGUSR1 and SIGVTALRM signals (SIGUSR1 and SIGVTALRM
* are used by preemption code).
*/
static int segvh();
static struct sigvec vec = {
segvh,
sigmask(SIGSEGV)|sigmask(SIGCHLD)|sigmask(SIGUSR1)|sigmask(SIGVTALRM),
1
};
extern void enable_interrupts();
extern int disable_interrupts();
static private int reenable_interrupts = 0;
#define DISABLE_INTERRUPTS() {reenable_interrupts = disable_interrupts();}
#define ENABLE_INTERRUPTS() {if (reenable_interrupts) enable_interrupts();}
private static int segvstack[512];
private static struct sigstack sigstruct = {(caddr_t)&segvstack[511], 0};
int sigstack();
char *getenv();
/*
_check_segv()
{
}
*/
_init_shbrk()
{
extern shared char _shend_;
/*
* Set up SIGSEGV handler; catch signal and grow shared-data
* and shared stack if appropriate.
*/
(void) sigstack(&sigstruct, (struct sigstack *)0);
(void) sigvec(SIGSEGV, &vec, (struct sigvec *)0);
/*
* Initialize state variables.
*/
curshbrk = myshbrk = &_shend_;
return(0);
}
/*
* shsbrk()
* shared-memory sbrk(); create new shared space, return start address.
*/
char *
shsbrk(incr)
int incr;
{
register slock_t *spin_ptr = &shbrk_lock;
char *val;
if (incr == 0)
return(curshbrk); /* note: can race with others! */
if (incr < 0) { /* can't shrink */
errno = EINVAL;
return((char *) -1);
}
/*
* Lock data-file to insure one shared-brk at a time (and
* stable value of curshbrk).
*/
DISABLE_INTERRUPTS();
S_LOCK(spin_ptr);
val = curshbrk;
if (lshbrk(val + incr) < 0)
val = (char *) -1;
S_UNLOCK(spin_ptr);
ENABLE_INTERRUPTS();
return(val);
}
/*
* shbrk()
* Add shared address space, analogous to brk().
*
* Just front-end to lshbrk() -- lock file and try to grow.
*/
shbrk(newbrk)
char *newbrk;
{
register slock_t *spin_ptr = &shbrk_lock;
int val;
DISABLE_INTERRUPTS();
S_LOCK(spin_ptr);
val = lshbrk(newbrk);
S_UNLOCK(spin_ptr);
ENABLE_INTERRUPTS();
return(val);
}
/*
* lshbrk()
* "Locked" shbrk(). Internal procedure.
*
* Assumes caller locked shmem file, to serialize access to this code.
* No need to check if running into bottom of UNIX private stack since
* threads run on their own stacks.
*/
static
lshbrk(newbrk)
register char *newbrk;
{
register char *cur; /* actual brk (rounded) */
register char *new; /* requested brk (rounded) */
extern shared char _shstart_; /* start of shared stuff */
/*
* Not allowed to shrink self (yet).
*/
if (newbrk < myshbrk) {
errno = EINVAL;
return(-1);
}
/*
* Growing: if no actual increase (rounding/etc), just adjust
* (self) myshbrk.
*/
cur = PGRND(myshbrk);
if (cur >= newbrk) {
myshbrk = newbrk;
if (newbrk > curshbrk)
curshbrk = myshbrk;
return(0);
}
new = PGRND(newbrk);
/*
* Need to mmap() more of file.
*/
if (MMAP(_shm_fd, cur, new - cur, cur - &_shstart_) < 0) {
errno = ENOMEM;
return(-1);
}
myshbrk = newbrk; /* maybe not aligned */
if (newbrk > curshbrk)
curshbrk = newbrk; /* grew the global memory */
return(0); /* success! */
}
/*
* _init_shstk()
* Initialize microtasking shared-stack.
*
* Called from _ppinit().
*/
int *
_init_shstk(ctxt_bottom, ctxt_top)
int *ctxt_bottom;
int *ctxt_top;
{
/*
* NOP -- never called since not using "microtask shared stack".
*/
return(0);
}
/*
* segvh()
* SIGSEGV handler.
*
* If process isn't up to max shared-data, get there and re-try the
* instruction. Else turn off handler and retry (==> dump core).
*/
/*ARGSUSED*/
static
segvh(sig, code, scp)
int sig, code;
struct sigcontext *scp;
{
register slock_t *spin_ptr = &shbrk_lock;
register int *fa = (int *)code;
/*
* A signal code of -1 indicates the signal originated from a
* kill() system call, rather than a real program fault.
*/
if (fa == (int *)-1) {
(void) signal(SIGSEGV, SIG_DFL);
(void) kill(getpid(), SIGSEGV);
return;
}
/*
* If process doesn't have all of shared heap mapped, map it and retry.
* Otherwise turn off SIGSEGV handling.
*
* Lock data-file during this to stabilize curshbrk and
* insure only one lshbrk() at a time.
*
* Return retries instruction, will die for real if turn off
* signal handling here.
*/
DISABLE_INTERRUPTS();
S_LOCK(spin_ptr);
if (myshbrk >= curshbrk || lshbrk(curshbrk) < 0)
(void) signal(SIGSEGV, SIG_DFL);
S_UNLOCK(spin_ptr);
ENABLE_INTERRUPTS();
}
#endif /* sequent */